package iagovsothello.online.client;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.SocketTimeoutException;

public class UDPDiscoverer extends Thread {

	private String serverAddress;
	private int serverPort;
	
	private String broadcastAddress;
	private int broadcastPort;
	private int timeoutMillis;
	
	public UDPDiscoverer(String broadcastAddress, int broadcastPort)
	{
		super();
		this.broadcastAddress = broadcastAddress;
		this.broadcastPort = broadcastPort;
		timeoutMillis = 0;
		this.serverAddress = null;
		this.serverPort = -1;
	}
	
	public String getServerAddress(int timeoutMillis)
	{
		if (serverAddress == null)
		{
			if (!isAlive())
			{
				this.timeoutMillis = timeoutMillis;
				setDaemon(true);
				start();
			}
			try {
				join();
			} catch (InterruptedException e) { }
		}
		return serverAddress;
	}
	
	public int getServerPort(int timeoutMillis)
	{
		if (serverPort < 0)
		{
			if (!isAlive())
			{	
				this.timeoutMillis = timeoutMillis;
				setDaemon(true);
				start();
			}
			try {
				join();
			} catch (InterruptedException e) { }
		}
		return serverPort;
	}
	
	public void run()
	{
		MulticastSocket socket = null;
		
		try {
			//creazione socket
			InetAddress address = InetAddress.getByName(broadcastAddress);
			socket = new MulticastSocket(broadcastPort);
			socket.joinGroup(address);
			socket.setTimeToLive(1);
			
			//creazione messaggio broadcast
			ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
			PrintWriter out = new PrintWriter(new OutputStreamWriter(bos,"UTF-8"));
			out.println("request address");
			out.flush();
			
			//invio messaggio
			byte buffer[] = bos.toByteArray();
			DatagramPacket packet = new DatagramPacket(buffer,buffer.length,address,broadcastPort);
			socket.send(packet);
			
			//attesa di risposta
			serverAddress = null;
			byte[] inputBuffer = new byte[1024];
			int time = timeoutMillis;
			long startingTime;
			do {
				startingTime = System.currentTimeMillis();
				DatagramPacket inputPacket = new DatagramPacket(inputBuffer, inputBuffer.length);
				try {
					socket.setSoTimeout(time);
					socket.receive(inputPacket);
					BufferedReader in = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(inputBuffer), "UTF-8"));
					if (in.readLine().equals("server address"))
					{
						serverAddress = in.readLine();
						serverPort = Integer.parseInt(in.readLine());
					}
				} catch (SocketTimeoutException e) { }
				time -= (System.currentTimeMillis()-startingTime);
			} while (time > 0 && serverAddress == null);
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (socket != null)
		{
			socket.close();
		}
	}
}
